package com.dragon.logical.service.contract.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dragon.common.model.ResultCode;
import com.dragon.common.model.exception.CustomException;
import com.dragon.common.util.ExportUtil;
import com.dragon.logical.service.contract.ContractService;
import com.dragon.logical.service.contract.DeliverService;
import com.dragon.repository.entity.*;
import com.dragon.repository.mapper.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

/**
 * <p>
 * 送货服务实现类
 * </p>
 *
 * @author sy
 * @since 2023-06-26
 */
@Service
public class DeliverServiceImpl extends ServiceImpl<DeliverMapper, Deliver> implements DeliverService {

    @Autowired
    DeliverMapper deliverMapper;
    @Autowired
    ProduceMapper produceMapper;

    @Autowired
    ContractMapper contractMapper;

    @Autowired
    PlanCollectMapper planCollectMapper;

    @Autowired
    AdminDepartmentMapper adminDepartmentMapper;

    @Autowired
    ContractService contractService;

    @Autowired
    DeliverProductsMapper deliverProductsMapper;

    @Autowired
    ProduceProductsMapper produceProductsMapper;

    @Autowired
    OtherFileMapper fileMapper;

    @Autowired
    RejectedProductMapper rejectedProductMapper;

    @Autowired
    RejectedMapper rejectedMapper;

    @Override
    public Page<Deliver> deliverList(String search, Integer status, Integer page, Integer limit, Integer type) {
        Page<Deliver> deliverPage = new Page<>(page, limit);
        return deliverMapper.selectDelivery(deliverPage, search, status, type);
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void addDeliver(Deliver deliver) {
        Produce produce = produceMapper.selectOne(new QueryWrapper<Produce>().lambda().eq(Produce::getId, deliver.getProduceId()));
        Contract contract = contractMapper.selectById(produce.getContractId());
        deliver.setContractId(produce.getContractId());
        deliver.setType(1);
        deliver.setSource(0);
        deliver.setStatus(1);
        deliver.setCustomerId(contract.getCustomerId());
        deliver.setCreateTime(DateUtil.date());
        deliver.setDeliveryId(contract.getDeliveryOfficer());
        deliverMapper.insert(deliver);
        //添加子表
        if (deliver.getDeliverProducts().size() == 0 || deliver.getDeliverProducts() == null) {
            throw new CustomException(ResultCode.DATA_NOT_FOUND.code(), "产品不能为空");
        }

        deliver.getDeliverProducts().forEach(deliverProducts -> {
            //获取需要送货的生产产品信息
            QueryWrapper<ProduceProducts> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(ProduceProducts::getProduceId, produce.getId())
                            .eq(ProduceProducts::getQuotesProductId,deliverProducts.getQuotesProductId());
            ProduceProducts produceProducts1 = produceProductsMapper.selectOne(wrapper);
            //生成送货单子数据
            //判断数量
            Integer deliverNum = produceProducts1.getDeliverNum() + deliverProducts.getOneNum();
            if(produceProducts1.getNum() < deliverNum ){
                throw new CustomException(ResultCode.DELIVER_NUM_INADEQUATE);
            }
            deliverProducts.setDeliverNum(deliverNum);
            deliverProducts.setDeliverId(deliver.getId());
            deliverProductsMapper.insert(deliverProducts);
            //修改生产单子数据
            ProduceProducts produceProducts = new ProduceProducts();
            produceProducts.setDeliverNum(deliverNum);
            produceProducts.setUpdateTime(DateUtil.date());
            produceProductsMapper.update(produceProducts, new LambdaQueryWrapper<ProduceProducts>().eq(ProduceProducts::getProduceId, produce.getId())
                    .eq(ProduceProducts::getQuotesProductId, deliverProducts.getQuotesProductId()));
        });
        // 如果来源是生产单则修改生产单主表数据
        List<ProduceProducts> produceProducts = produceProductsMapper.selectList(new LambdaQueryWrapper<ProduceProducts>().eq(ProduceProducts::getProduceId, deliver.getProduceId()));

        AtomicReference<Boolean> isDeliver = new AtomicReference<>(true);
        produceProducts.forEach(e -> {
            if (!e.getDeliverNum().equals(e.getNum())) {
                isDeliver.set(false);
            }
        });

        if (isDeliver.get()) {
            //修改主表状态
            produce.setDeliverStatus(2);
        } else {
            if (!produce.getDeliverStatus().equals(1)) produce.setDeliverStatus(1);
        }
        produceMapper.updateById(produce);
    }


    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void addRejectedDeliver(Deliver deliver){
        Produce produce = produceMapper.selectOne(new QueryWrapper<Produce>().lambda().eq(Produce::getId, deliver.getProduceId()));
        Contract contract = contractMapper.selectById(produce.getContractId());
        deliver.setContractId(produce.getContractId());
        Rejected rejected = rejectedMapper.selectById(deliver.getRejectedId());
        deliver.setType(1);
        deliver.setStatus(1);
        deliver.setSource(1);
        deliver.setCustomerId(contract.getCustomerId());
        deliver.setProduceId(produce.getId());
        deliver.setCreateTime(DateUtil.date());
        deliver.setDeliveryId(contract.getDeliveryOfficer());
        deliverMapper.insert(deliver);
        //添加子表
        if (deliver.getDeliverProducts().size() == 0 || deliver.getDeliverProducts() == null) {
            throw new CustomException(ResultCode.DATA_NOT_FOUND.code(), "产品不能为空");
        }
        AtomicReference<Boolean> isDeliver = new AtomicReference<>(true);
        deliver.getDeliverProducts().forEach(deliverProducts -> {
            //生成送货单子数据
            Integer deliverNum = deliverProducts.getDeliverNum() + deliverProducts.getOneNum();
            if(deliverProducts.getNum() < deliverNum ){
                throw new CustomException(ResultCode.REJECTED_NUM_INADEQUATE);
            }
            deliverProducts.setDeliverNum(deliverNum);
            deliverProducts.setDeliverId(deliver.getId());
            deliverProductsMapper.insert(deliverProducts);
            //修改生产单子数据
            RejectedProduct rejectedProduct = rejectedProductMapper.selectOne(new LambdaQueryWrapper<RejectedProduct>().eq(RejectedProduct::getRejectedId, deliver.getRejectedId())
                    .eq(RejectedProduct::getProductId, deliverProducts.getProductId()));
            rejectedProduct.setDeliverNum(deliverNum);
            rejectedProduct.setUpdateTime(DateUtil.date());
            rejectedProductMapper.updateById(rejectedProduct);
            if(deliverNum < rejectedProduct.getRecededNum()){
                isDeliver.set(false);
            }
        });

        if (isDeliver.get()) {
            //修改主表状态
            rejected.setDeliverStatus(2);

        } else {
            if (!rejected.getDeliverStatus().equals(1)) rejected.setDeliverStatus(1);
        }
        rejectedMapper.updateById(rejected);

        List<Produce> produceList = produceMapper.selectList(new QueryWrapper<Produce>().lambda().eq(Produce::getRejectedId, deliver.getRejectedId()));
        if (produceList.size() != 0){
            produceList.forEach(produce1 -> {
                produce1.setDeliverStatus(1);
                produceMapper.updateById(produce1);
            });
        }
    }

    @Override
    public void update(Deliver deliver) {
        Deliver one = deliverMapper.selectById(deliver.getId());
        if (one == null) {
            throw new CustomException(ResultCode.DATA_NOT_FOUND);
        }
        deliver.setUpdateTime(DateUtil.date());
        deliverMapper.updateById(deliver);
    }

    @Override
    public void delete(Integer id) {
        Deliver one = deliverMapper.selectById(id);
        if (one == null) {
            throw new CustomException(ResultCode.DATA_NOT_FOUND);
        }
        deliverMapper.deleteById(id);
    }

    @Override
    public List<Deliver> selectByContractId(Integer contractId) {
        QueryWrapper<Deliver> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Deliver::getContractId, contractId);
        List<Deliver> delivers = deliverMapper.selectDeliveryList(wrapper);
        return delivers;
    }

    @Override
    public Deliver listByDeliverId(Integer id) {
        Deliver deliver = deliverMapper.selectDeliveryById(id);
        List<DeliverProducts> deliverProducts = deliverProductsMapper.selectList(new QueryWrapper<DeliverProducts>().lambda()
                .eq(DeliverProducts::getDeliverId, id));
        List<OtherFile> otherFiles = fileMapper.selectList(new QueryWrapper<OtherFile>().lambda().eq(OtherFile::getCorrelationId, id)
                .eq(OtherFile::getStreamType, 4));
        if (otherFiles != null){
            deliver.setOtherFileList(otherFiles);
        } else {
            deliver.setOtherFileList(new ArrayList<>());
        }
        if(deliverProducts != null){
            deliver.setDeliverProducts(deliverProducts);
        }
        return deliver;
    }


    @Override
    public String selectCustomerAddressByContractId(Integer contractId) {
        return contractService.selectCustomerAddressByContractId(contractId);
    }

    @Override
    public void updateStatus(Deliver deliver1) {
        Deliver deliver = deliverMapper.selectById(deliver1.getId());

        if(deliver.getType() == 2){
            throw new CustomException(ResultCode.DELIVER_IS_AUDIT);
        }

        deliver.setType(2);
        deliver.setUpdateTime(DateUtil.date());
        deliver.setDeliveryTime(DateUtil.date());
        deliverMapper.updateById(deliver);
        //附件添加
        List<OtherFile> otherFileList = deliver1.getOtherFileList();
        if (otherFileList != null) {
            otherFileList.forEach(file -> {
                file.setCorrelationId(deliver1.getId());
                file.setStreamType(4);
                fileMapper.insert(file);
            });
        }
        //判断生产子表合同数量是否完成,检测子表是否送货完成
        List<ProduceProducts> deliverProducts = produceProductsMapper.selectList(new LambdaQueryWrapper<ProduceProducts>()
                .eq(ProduceProducts::getProduceId, deliver.getProduceId()));
        AtomicReference<Boolean> isDeliver = new AtomicReference<>(true);
        deliverProducts.forEach(deliverProducts1 -> {
            // 合同已完成
            if (deliverProducts1.getDeliverNum() < deliverProducts1.getNum()) {
                isDeliver.set(false);
            }
        });
        if (isDeliver.get().equals(true) && deliver.getSource() == 0) {
            Contract contract = contractMapper.selectById(deliver.getContractId());
//            if(contract.getSettlement() == 1){
                if ((contract.getPaymentMethod() == 1 && contract.getCombination() == 2) || contract.getPaymentMethod() == 2) {
                    Double money = (double) 0;
                    if (contract.getPaymentMethod() == 1 && contract.getCombination() == 2) {
                        money = contract.getMoney() - contract.getPrepaymentMoney();
                    } else {
                        money = contract.getMoney();
                    }
                    if (contract.getSupplementMoney() == null){
                        contract.setSupplementMoney(0.00);
                    }
                    QueryWrapper<AdminDepartment> queryWrapper = new QueryWrapper<>();
                    queryWrapper.lambda().eq(AdminDepartment::getAdminId, contract.getPayee());
                    AdminDepartment adminDepartment = adminDepartmentMapper.selectOne(queryWrapper);
                    PlanCollect planCollect = new PlanCollect();
                    planCollect.setContractId(contract.getId());
                    planCollect.setCustomerId(contract.getCustomerId());
                    planCollect.setActualPlanMoney(0.00);
                    planCollect.setCreateTime(DateUtil.date());
                    planCollect.setRefundMoney(contract.getRefundMoney());
                    planCollect.setAdminId(contract.getPayee());
                    //结算方式
                    planCollect.setSettlementType(contract.getSettlement() == 1 ? 1 : 2);
                    planCollect.setPlanMoney(money + contract.getSupplementMoney());
                    planCollect.setDepartmentId(adminDepartment.getDepartmentId());
                    planCollect.setPlanTime(DateUtil.offsetDay(DateUtil.date(), 1));
                    planCollectMapper.insert(planCollect);
                }
//            } else {
//                QueryWrapper<AdminDepartment> queryWrapper = new QueryWrapper<>();
//                queryWrapper.lambda().eq(AdminDepartment::getAdminId, contract.getPayee());
//                AdminDepartment adminDepartment = adminDepartmentMapper.selectOne(queryWrapper);
//                PlanCollect planCollect = new PlanCollect();
//                planCollect.setContractId(contract.getId());
//                planCollect.setCreateTime(DateUtil.date());
//                planCollect.setAdminId(contract.getPayee());
//                //结算方式
//                planCollect.setSettlementType(contract.getSettlement() == 1 ? 1 : 2);
//                planCollect.setPlanMoney(contract.getMoney());
//                planCollect.setDepartmentId(adminDepartment.getDepartmentId());
//                planCollect.setPlanTime(DateUtil.offsetDay(DateUtil.date(), 1));
//                planCollectMapper.insert(planCollect);
//            }
        }
    }

    @Override
    public List<DeliverProducts> selectDeliverProductById(Integer id) {
        //送货产品
        List<DeliverProducts> deliverProducts = deliverProductsMapper.selectListByDeliver(null, id);
        return deliverProducts;
    }


    @Override
    public void exportExcel(Integer id, HttpServletResponse response)throws UnsupportedEncodingException {
        Deliver deliver = deliverMapper.selectById(id);
        List<List<Object>> rowTotal = new ArrayList<>();
        List<Object> row1 = CollUtil.newArrayList("产品名称", "规格型号", "材质", "合同数量","已发货数量","本次发货数量");
        rowTotal.add(row1);
        List<DeliverProducts> deliverProducts = selectDeliverProductById(id);
        deliverProducts.forEach(deliverProducts1 -> {
            List<Object> row = CollUtil.newArrayList(deliverProducts1.getName(),deliverProducts1.getSpecification(),
                    deliverProducts1.getVProductMaterial(),deliverProducts1.getNum().toString(),
                    deliverProducts1.getDeliverNum().toString(),deliverProducts1.getOneNum().toString());
            rowTotal.add(row);
        });
        ExportUtil.exportExcel(rowTotal,response,deliver.getName());
    }

    @Override
    public Page<Deliver> informationOfDeliver(Integer page, Integer limit, Integer contractId) {
        Page<Deliver> deliverPage = new Page<>(page, limit);
        Page<Deliver> deliverPage1 = deliverMapper.selectPageAndContract(deliverPage, contractId);
        deliverPage1.getRecords().forEach( deliver -> {
            List<DeliverProducts> deliverProducts = deliverProductsMapper.selectListByDeliver(null,deliver.getId());
            if (deliverProducts != null){
                deliver.setDeliverProducts(deliverProducts);
            }
        });
        return deliverPage1;
    }
}
